package com.kclm.se.nio;

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/******
 * 
 * @author yejf
 * @since JDK8.0
 * @CreateDate 2020年8月29日 下午4:27:08 
 * @description 此类用来描述了 JAVA NIO的选择器的使用
 * 注：由于FileChannel不支持注册到 Selector中，所以，此例使用了 ServerSocketChannel和SocketChannel
 *
 */
public class SelectorDemo {

	public static void main(String[] args) throws Exception {
		//定义端口
		int port = 9090;
		//创建 ServletSocketChannel
		ServerSocketChannel server = ServerSocketChannel.open();
		//绑定端口
		server.bind(new InetSocketAddress(port));
		//设置为非阻塞
		server.configureBlocking(false);
		//创建 选择器
		Selector selector = Selector.open();
		//把server注册到此选择器
		SelectionKey key = server.register(selector, SelectionKey.OP_ACCEPT);
		//上面的key就是注册到此选择器中的 ServerSocketChannel对象
		System.out.println("服务器启动后，并已注册到多路复用器中.");
		System.out.println(key);
		//循环
		while(true) {
			//
			System.out.println("注册的Channel有："+selector.keys().size()+" 路");
			//
			while(selector.select() > 0) { //select 方法会阻塞 [可以指定超时时间，单位毫秒]
				//获取所有准备好的channel: 这里总是可以拿到注册进去的ServerSocketChannel的
				Set<SelectionKey> selectionKeys = selector.selectedKeys();
				Iterator<SelectionKey> iter = selectionKeys.iterator();
				while(iter.hasNext()) {
					SelectionKey selectionKey = iter.next();
					//判断
					if(selectionKey.isAcceptable()) {
						System.out.println("Acceptable.....");
						//
						ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
						//调用accept方法接收客户端的连接
						SocketChannel client = ssc.accept();
						//配置非阻塞
						client.configureBlocking(false);
						//注册到 选择器上
						client.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
						
						System.out.println("------------------------------------------------");
						System.out.printf("新客户端：%s\n", client.getRemoteAddress());
						System.out.println("------------------------------------------------");
						
					} else if(selectionKey.isConnectable()) {
						System.out.println("Connectable.....");
						
					} else if(selectionKey.isReadable()) {
						System.out.println("Readable.....");
						
					} else if(selectionKey.isWritable()) {
						System.out.println("Writable.....");
						
					} else {
						System.out.println("--- 未知状态...");
					}
					//一定要移除这个项
					iter.remove();
				}
			}
		}
	}
}
